/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package chat.mybean;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.beans.BeanDescriptor;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;

/**
 *
 * @author spider391Tang
 */
public class BeanEditor extends JDialog implements PropertyChangeListener {

    protected Component m_bean;
    protected JTable m_table;
    protected PropertyTableData m_data;

    public BeanEditor(Component bean, Point pt) {
        m_bean = bean;
        m_bean.addPropertyChangeListener(this);

        //Point pt = m_bean.getLocationOnScreen();
        //Point pt = new Point(100,100);
        setBounds(pt.x + 50, pt.y + 10, 400, 300);
        getContentPane().setLayout(new BorderLayout());

        m_data = new PropertyTableData(m_bean);
        m_table = new JTable((TableModel) m_data);

        JScrollPane ps = new JScrollPane();
        ps.getViewport().add(m_table);
        getContentPane().add(ps, BorderLayout.CENTER);

        //setDefaultCloseOperation(HIDE_ON_CLOSE);
        //setVisible(true);
    }

    public void propertyChange(PropertyChangeEvent evt) {
        m_data.setProperty(evt.getPropertyName(), evt.getNewValue());
    }

    class IconData {

        public ImageIcon m_icon;
        public Object m_data;

        public IconData(ImageIcon icon, Object data) {
            m_icon = icon;
            m_data = data;
        }
    }

    class PropertyTableData extends AbstractTableModel {

        protected String[][] m_properties;
        protected int m_numProps = 0;
        protected Vector m_v;

        public PropertyTableData(Component bean,int aa) {
            try {
                BeanInfo info = Introspector.getBeanInfo(
                        m_bean.getClass());
                BeanDescriptor descr = info.getBeanDescriptor();
                setTitle("Editing " + descr.getName());
                PropertyDescriptor[] props = info.getPropertyDescriptors();
                m_numProps = props.length;

                m_v = new Vector(m_numProps);
                for (int k = 0; k < m_numProps; k++) {
                    String name = props[k].getDisplayName();
                    boolean added = false;
                    for (int i = 0; i < m_v.size(); i++) {
                        String str = ((PropertyDescriptor) m_v.elementAt(i)).getDisplayName();
                        if (name.compareToIgnoreCase(str) < 0) {
                            m_v.insertElementAt(props[k], i);
                            added = true;
                            break;
                        }
                    }
                    if (!added) {
                        m_v.addElement(props[k]);
                    }
                }

                m_properties = new String[m_numProps][2];
                for (int k = 0; k < m_numProps; k++) {
                    PropertyDescriptor prop =
                            (PropertyDescriptor) m_v.elementAt(k);
                    m_properties[k][0] = prop.getDisplayName();
                    
                    Method mRead = prop.getReadMethod();
                    if (mRead != null
                            && mRead.getParameterTypes().length == 0) {
                        Object value = mRead.invoke(m_bean, null);
                        m_properties[k][1] = objToString(value);
                    } else {
                        m_properties[k][1] = "error";
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
                JOptionPane.showMessageDialog(
                        BeanEditor.this, "Error: " + ex.toString(),
                        "Warning", JOptionPane.WARNING_MESSAGE);
            }
        }

        public PropertyTableData(Component bean) {
            try {
                BeanInfo info = Introspector.getBeanInfo(
                        m_bean.getClass());
                BeanDescriptor descr = info.getBeanDescriptor();
                setTitle("Editing " + descr.getName());
                //PropertyDescriptor[] props = info.getPropertyDescriptors();

                m_v = new Vector();
                for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
                    String field_name = pd.getName(); // get property (or field) name
                    //Method get_method = pd.getReadMethod();  // get getField()
                    //Method set_method = pd.getWriteMethod(); // get setField()
                    if (field_name.startsWith("wb")) {
                        m_v.addElement(pd);
                        m_numProps++;
                    }
                }

                m_properties = new String[m_numProps][2];
                for (int k = 0; k < m_numProps; k++) {
                    PropertyDescriptor prop =
                            (PropertyDescriptor) m_v.elementAt(k);
                    m_properties[k][0] = prop.getDisplayName().substring(2);

                    //System.out.println(prop.getDisplayName());
                    Method mRead = prop.getReadMethod();
                    if (mRead != null
                            && mRead.getParameterTypes().length == 0) {
                        Object value = mRead.invoke(m_bean, null);
                        m_properties[k][1] = objToString(value);
                    } else {
                        m_properties[k][1] = "error";
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
                JOptionPane.showMessageDialog(
                        BeanEditor.this, "Error: " + ex.toString(),
                        "Warning", JOptionPane.WARNING_MESSAGE);
            }
        }

        public void setProperty(String name, Object value) {
            System.out.println("[client] Property " + name + "is changed.");
            for (int k = 0; k < m_numProps; k++) {
                if (name.equals(m_properties[k][0])) {
                    m_properties[k][1] = objToString(value);
                    m_table.tableChanged(new TableModelEvent(this, k));
                    m_table.repaint();
                    break;
                }
            }
        }

        public int getRowCount() {
            return m_numProps;
        }

        public int getColumnCount() {
            return 2;
        }

        public String getColumnName(int nCol) {
            return nCol == 0 ? "Property" : "Value";
        }

        public boolean isCellEditable(int nRow, int nCol) {
            return (nCol == 1);
        }

        public Object getValueAt(int nRow, int nCol) {
            if (nRow < 0 || nRow >= getRowCount()) {
                return "";
            }
            switch (nCol) {
                case 0:
                    return m_properties[nRow][0];
                case 1:
                    return m_properties[nRow][1];
            }
            return "";
        }

        public void setValueAt(Object value, int nRow, int nCol) {

            if (nRow < 0 || nRow >= getRowCount()) {
                return;
            }
            /// 公子乖 -　在這裡做出是否要跳出 color dlg 的判斷


            String str = value.toString();
            System.out.println(str);
            PropertyDescriptor prop = (PropertyDescriptor) m_v.elementAt(nRow);
            Class cls = prop.getPropertyType();
            System.out.println(cls.getName());
            if(cls.getName().compareTo("java.awt.Color") == 0){
                ColorEditor colorEditor = new ColorEditor();
                //String s = colorEditor.getColor();
                str = colorEditor.getColor().getRed()+","+colorEditor.getColor().getGreen()+","+colorEditor.getColor().getBlue();
                System.out.println(str);
            }
            //System.out.println(cls);
            //if(cls instanceof Color)
            //    System.out.println("This is color type");


            Object obj = stringToObj(str, cls);
            if (obj == null) {
                System.out.println("[BeanEditro] can't process");
                return;        // can't process
            }
            Method mWrite = prop.getWriteMethod();
            if (mWrite == null || mWrite.getParameterTypes().length != 1) {
                return;
            }
            try {
                mWrite.invoke(m_bean, new Object[]{obj});

                /// 公子乖 -　Debug 後拿掉的，因為不會 repaint
                //m_bean.getParent().doLayout();
                //m_bean.getParent().repaint();
                //m_bean.repaint();
            } catch (Exception ex) {
                ex.printStackTrace();
                JOptionPane.showMessageDialog(
                        BeanEditor.this, "Error: " + ex.toString(),
                        "Warning", JOptionPane.WARNING_MESSAGE);
            }
            m_properties[nRow][1] = str;
        }

        public String objToString(Object value) {
            if (value == null) {
                return "null";
            }
            if (value instanceof Dimension) {
                Dimension dim = (Dimension) value;
                return "" + dim.width + "," + dim.height;
            } else if (value instanceof Insets) {
                Insets ins = (Insets) value;
                return "" + ins.left + "," + ins.top + "," + ins.right + "," + ins.bottom;
            } else if (value instanceof Rectangle) {
                Rectangle rc = (Rectangle) value;
                return "" + rc.x + "," + rc.y + "," + rc.width + "," + rc.height;
            } else if (value instanceof Color) {
                Color col = (Color) value;
                return "" + col.getRed() + "," + col.getGreen() + "," + col.getBlue();
            }
            return value.toString();
        }

        public Object stringToObj(String str, Class cls) {
            try {
                if (str == null) {
                    return null;
                }
                String name = cls.getName();
                if (name.equals("java.lang.String")) {
                    return str;
                } else if (name.equals("int")) {
                    return new Integer(str);
                } else if (name.equals("long")) {
                    return new Long(str);
                } else if (name.equals("float")) {
                    return new Float(str);
                } else if (name.equals("double")) {
                    return new Double(str);
                } else if (name.equals("boolean")) {
                    return new Boolean(str);
                } else if (name.equals("java.lang.Integer")) {
                    return new Integer(str);
                } else if (name.equals("java.awt.Dimension")) {
                    int[] i = strToInts(str);
                    return new Dimension(i[0], i[1]);
                } else if (name.equals("java.awt.Insets")) {
                    int[] i = strToInts(str);
                    return new Insets(i[0], i[1], i[2], i[3]);
                } else if (name.equals("java.awt.Rectangle")) {
                    int[] i = strToInts(str);
                    return new Rectangle(i[0], i[1], i[2], i[3]);
                } else if (name.equals("java.awt.Color")) {
                    int[] i = strToInts(str);
                    return new Color(i[0], i[1], i[2]);
                }
                return null;    // not supported
            } catch (Exception ex) {
                return null;
            }
        }

        public int[] strToInts(String str) throws Exception {
            int[] i = new int[4];
            StringTokenizer tokenizer = new StringTokenizer(str, ",");
            for (int k = 0; k < i.length
                    && tokenizer.hasMoreTokens(); k++) {
                i[k] = Integer.parseInt(tokenizer.nextToken());
            }
            return i;
        }
    }
}

